//
// Created by song on 16-11-18.
//

#ifndef C0COMPILER_TOKEN_H
#define C0COMPILER_TOKEN_H

#include <string>
#include <map>
#include "../Config.h"

// each token can only be of the 'leaf' type.
// but they also belongs to their parent type.
// you can use their parent type later in the parser.
enum TokenType{
    Id,
    /***///SystemFun,
    /***//***/Scanf,
    /***//***/Printf,
    Num,
    //Type,
    /***/CommonType,
    /***//***/Int,
    /***//***/Char,
    /***/Void,
    //Operator,
    /***///AlgebraicOp,
    /***//***///AddSubOp,
    /***//***//***/Add,
    /***//***//***/Minus,
    /***//***///MultiDivOp,
    /***//***//***/Mul,
    /***//***//***/Div,
    /***///RelationOp,
    /***//***/LessThan,
    /***//***/LessEqual,
    /***//***/GreatThan,
    /***//***/GreatEqual,
    /***//***/NotEqual,
    /***//***/Equal,
    //Qualifier,
    /***/LeftR,//  (
    /***/RightR,// )
    /***/LeftB,//  {
    /***/RightB,// }
    /***/LeftS,//  [
    /***/RightS,// ]
    /***/Comma,//  ,
    /***/Semicolon,// ;
    /***/Colon,//  :
    Assign,// =
    //Keyword,
    /***/If,
    /***/Else,
    /***/While,
    /***/Default,
    /***/Case,
    /***/Return,
    /***/Switch,
    /***/Const,
    CharLiteral,
    StringLiteral,
    EndOfFile
};



class Token{

public:
    Token(TokenType t, string content, int sourceIndex, int length) {
        this->type = t;
        this->content = content;
        this->sourceIndex = sourceIndex;
        this->length = length;
    }

    string toString(){
        string typeStr = TokenTypeStr[this->type];
        unsigned long fill = (TYPE_PRINT_LENGTH - typeStr.size());
        string whiteSpace(fill,' ');
        return typeStr + whiteSpace + this->content;
    }

    string content;
    TokenType type;
    int sourceIndex;
    int length;

    static map<TokenType,string> TokenTypeStr;
    static void init(){
        TokenTypeStr[Id]=          "IDENTIFIER";
//        TokenTypeStr[SystemFun]=   "SYSTEM_FUNCTION";
        TokenTypeStr[Scanf]=       "SYS.SCANF";
        TokenTypeStr[Printf]=      "SYS.PRINTF";
        TokenTypeStr[Num]=         "NUMBER";
//        TokenTypeStr[Type]=        "TYPE";
        TokenTypeStr[CommonType]=  "COMMON_TYPE";
        TokenTypeStr[Int]=         "TYPE.INTEGER";
        TokenTypeStr[Char]=        "TYPE.CHAR";
        TokenTypeStr[Void]=        "TYPE.VOID";
//        TokenTypeStr[Operator]=    "OPERATOR";
//        TokenTypeStr[AlgebraicOp]= "OP.ALGEBRAIC";
//        TokenTypeStr[AddSubOp]=    "OP.ADD_OR_SUB";
        TokenTypeStr[Add]=         "OP.ADD";
        TokenTypeStr[Minus]=       "OP.SUB";
//        TokenTypeStr[MultiDivOp]=  "OP.MUL_OR_DIV";
        TokenTypeStr[Mul]=         "OP.MUL";
        TokenTypeStr[Div]=         "OP.DIV";
//        TokenTypeStr[RelationOp]=  "OP.RELATIONAL";
        TokenTypeStr[LessThan]=    "OP.LESS_THAN";
        TokenTypeStr[LessEqual]=   "OP.LESS_EQUAL";
        TokenTypeStr[GreatThan]=   "OP.GREAT_THAN";
        TokenTypeStr[GreatEqual]=  "OP.GREAT_EQUAL";
        TokenTypeStr[NotEqual]=    "OP.NOT_EQUAL";
        TokenTypeStr[Equal]=       "OP.EQUAL";
//        TokenTypeStr[Qualifier]=   "QUALIFIER";
        TokenTypeStr[LeftR]=       "Q.LEFT_ROUND_P";
        TokenTypeStr[RightR]=      "Q.RIGHT_ROUND_P";
        TokenTypeStr[LeftB]=       "Q.LEFT_BRACE";
        TokenTypeStr[RightB]=      "Q.RIGHT_BRACE";
        TokenTypeStr[LeftS]=       "Q.LEFT_SQUARE_P";
        TokenTypeStr[RightS]=      "Q.RIGHT_SQUARE_P";
        TokenTypeStr[Comma]=       "Q.COMMA";
        TokenTypeStr[Semicolon]=   "Q.SEMICOLON";
        TokenTypeStr[Colon]=       "Q.COLON";
        TokenTypeStr[Assign]=      "ASSIGN";
//        TokenTypeStr[Keyword]=     "KEYWORD";
        TokenTypeStr[If]=          "KEYWORD.IF";
        TokenTypeStr[If]=          "KEYWORD.ELSE";
        TokenTypeStr[While]=       "KEYWORD.WHILE";
        TokenTypeStr[Default]=     "KEYWORD.DEFAULT";
        TokenTypeStr[Case]=        "KEYWORD.CASE";
        TokenTypeStr[Return]=      "KEYWORD.RETURN";
        TokenTypeStr[Switch]=      "KEYWORD.SWITCH";
        TokenTypeStr[Const]=       "KEYWORD.CONST";
        TokenTypeStr[CharLiteral]= "CHAR_LITERAL";
        TokenTypeStr[StringLiteral]="STRING_LITERAL";
    }
};


#endif //C0COMPILER_TOKEN_H
